package com.agileai.hotweb.servlet;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;

import com.agileai.domain.DataParam;
import com.agileai.hotweb.bizmoduler.frame.OnlineCounterService;
import com.agileai.hotweb.common.BeanFactory;
import com.agileai.hotweb.common.Constants;
import com.agileai.hotweb.common.Constants.FrameHandlers;
import com.agileai.hotweb.common.HandlerParser;
import com.agileai.hotweb.controller.core.BaseHandler;
import com.agileai.hotweb.domain.core.Profile;
import com.agileai.hotweb.renders.AjaxRenderer;
import com.agileai.hotweb.renders.RedirectRenderer;
import com.agileai.hotweb.renders.ViewRenderer;
import com.agileai.util.ListUtil;
import com.agileai.util.StringUtil;

public class DispatchServlet extends HttpServlet {
	protected Logger log = Logger.getLogger(this.getClass());
	protected static HashMap<ClassLoader,List<String>> PublicHandlerIdListCache = new HashMap<ClassLoader,List<String>>();
	private static final long serialVersionUID = 1489970485928178334L;
	
	final public void init() throws ServletException {
		super.init();
		String serviceConfigLocation = this.getServletContext().getInitParameter(Constants.ConfigFile.SERVICE);
		if (!StringUtil.isNullOrEmpty(serviceConfigLocation)){
			BeanFactory.init(serviceConfigLocation);			
		}
		String handlerConfigLocation = this.getServletContext().getInitParameter(Constants.ConfigFile.HANDLER);
		if (!StringUtil.isNullOrEmpty(handlerConfigLocation)){
			HandlerParser.init(handlerConfigLocation);
		}
		String beanId = this.getServletContext().getInitParameter(Constants.OnlineCounterServiceKey);
		if (!StringUtil.isNullOrEmpty(beanId)){
			OnlineCounterService onlineCounterService = (OnlineCounterService)BeanFactory.instance().getBean(beanId);
			onlineCounterService.initOnlineCount();
		}
		ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
		List<String> publicHandlerIdList = PublicHandlerIdListCache.get(classLoader);
		String publicHandlerIds = this.getInitParameter(Constants.PublicHandlerIdsKey);
		if (publicHandlerIdList == null){
			publicHandlerIdList = new ArrayList<String>();
			PublicHandlerIdListCache.put(classLoader, publicHandlerIdList);
			if (!StringUtil.isNullOrEmpty(publicHandlerIds)){
				String[] publicHandlerIdArray = publicHandlerIds.split(",");
				ListUtil.addArrayToList(publicHandlerIdList, publicHandlerIdArray);
			}
		}
		this.initResource();
	}
	final public void doGet(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {
		this.process(request, response);
	}
	final public void doPost(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {
		this.process(request, response);
	}
	protected void initResource(){
		
	}
	
	protected void process(HttpServletRequest request, HttpServletResponse response) 
		throws ServletException, IOException{
		log.debug("DispatchServlet------start");
		try {
			ViewRenderer viewRenderer = null;
			String handlerId = parseHandlerId(request);
			ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
			List<String> publicHandlerIdList = PublicHandlerIdListCache.get(classLoader);
			if (isExpired(request) 
					&& !FrameHandlers.LoginHandlerId.equals(handlerId)
					&& !publicHandlerIdList.contains(handlerId)){
				if (!Constants.FrameHandlers.MenuTreeHandlerId.equals(handlerId)){
					viewRenderer = new RedirectRenderer(request.getContextPath());	
				}
				else{
					StringBuffer responseText = new StringBuffer();
					String contextPath = request.getContextPath();
					responseText.append("parent.location.href='").append(contextPath).append("'");
					viewRenderer = new AjaxRenderer(responseText.toString());					
				}
			}
			else{
				BaseHandler handler = HandlerParser.getOnly().instantiateHandler(handlerId);
				handler.setDispatchServlet(this);
				handler.setRequest(request);
				handler.setResponse(response);
				DataParam param = new DataParam(request.getParameterMap());
				viewRenderer = handler.processRequest(param);
				viewRenderer.setHandler(handler);
			}
			viewRenderer.executeRender(this, request, response);	
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		log.debug("DispatchServlet------end");
	}
	protected boolean isExpired(HttpServletRequest request){
		boolean result = true;
		HttpSession session = request.getSession(false);
		if (session != null){
			Profile profile = (Profile)session.getAttribute(Profile.PROFILE_KEY);
			if (profile != null){
				result = false;				
			}
		}
		return result;
	}

	protected String parseHandlerId(HttpServletRequest request) {
		String result = "";
		String queryString = request.getQueryString().trim();
		int firstIndex = queryString.indexOf("actionType=");
		if (firstIndex < 0) {
			int endIndex = queryString.length();
			int tempIndex = queryString.indexOf("&");
			if (tempIndex > -1) {
				endIndex = tempIndex;
			}
			result = queryString.substring(0, endIndex);
		} else {
			int lastIndex = queryString.lastIndexOf("actionType=");
			if (firstIndex == lastIndex) {
				int endIndex = queryString.length();
				int tempIndex = queryString.indexOf("&");
				if (tempIndex > -1) {
					endIndex = tempIndex;
				}
				result = queryString.substring(0, endIndex);
			} else {
				String temp = queryString.substring(0, lastIndex - 1);
				int index = temp.lastIndexOf("&");
				result = temp.substring(index + 1, temp.length());
			}
		}
		return result;
	}
}
